package com.jasmine.auth.interceptor;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.StrUtil;
import com.jasmine.auth.TokenContextHolder;
import com.jasmine.auth.TokenManager;
import com.jasmine.auth.annotation.AuthIgnore;
import com.jasmine.auth.annotation.AuthReject;
import com.jasmine.auth.exception.NoneTokenException;
import com.jasmine.auth.exception.UnauthorizedRequestException;
import com.jasmine.auth.model.Token;
import com.jasmine.core.constants.BjsConstants;
import com.jasmine.core.util.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author : jasmineXz
 */
@Component
public class AuthInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(AuthInterceptor.class);

    @Autowired
    private TokenManager tokenManager;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String url = request.getRequestURI();
        log.info("[BJSTK] [{}] [{}] {}", WebUtil.getIP(request), WebUtil.methodWrapper(request.getMethod()), url);

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        if (null != AnnotationUtil.getAnnotation(handlerMethod.getMethod(), AuthReject.class) )
            throw new UnauthorizedRequestException();
        if (null != AnnotationUtil.getAnnotation(handlerMethod.getMethod(), AuthIgnore.class) )
            return true;

        String token = request.getHeader(BjsConstants.HTTP_HEADER_AUTHORIZATION);

        // 1. 没有token
        if(StrUtil.isBlank(token) || StrUtil.replace(token,BjsConstants.Token.TOKEN_PREFIX,"").length() < 1)
            throw new NoneTokenException();

        // 2. token非法
        try {
            Token tokenContext = tokenManager.getAccessToken(token);
            /*
             * 将token放入ThreadLocal上下文
             */
            TokenContextHolder.setContext(tokenContext);
        } catch (Exception e) {
            tokenManager.getRefreshToken(token);
        }
        tokenManager.resetToken(token);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }

    /**
     * 清除Token ThreadLocal 上下文
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        TokenContextHolder.removeContext();
    }


}
